home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #3 / Amiga Plus CD - 2002 - No. 03.iso / AmigaPlus / Tools / Development / stunnel-4.04 / _src / src / pty.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-01-01  |  8.0 KB  |  277 lines

  1. /*
  2.  *   stunnel       Universal SSL tunnel
  3.  *   Copyright (c) 1998-2003 Michal Trojnara <Michal.Trojnara@mirt.net>
  4.  *                 All Rights Reserved
  5.  *
  6.  *   Based on a Public Domain code by Tatu Ylonen <ylo@cs.hut.fi>
  7.  *
  8.  *   This program is free software; you can redistribute it and/or modify
  9.  *   it under the terms of the GNU General Public License as published by
  10.  *   the Free Software Foundation; either version 2 of the License, or
  11.  *   (at your option) any later version.
  12.  *
  13.  *   This program is distributed in the hope that it will be useful,
  14.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *   GNU General Public License for more details.
  17.  *
  18.  *   You should have received a copy of the GNU General Public License
  19.  *   along with this program; if not, write to the Free Software
  20.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  *   In addition, as a special exception, Michal Trojnara gives
  23.  *   permission to link the code of this program with the OpenSSL
  24.  *   library (or with modified versions of OpenSSL that use the same
  25.  *   license as OpenSSL), and distribute linked combinations including
  26.  *   the two.  You must obey the GNU General Public License in all
  27.  *   respects for all of the code used other than OpenSSL.  If you modify
  28.  *   this file, you may extend this exception to your version of the
  29.  *   file, but you are not obligated to do so.  If you do not wish to
  30.  *   do so, delete this exception statement from your version.
  31.  */
  32.  
  33. #include "common.h"
  34. #include "prototypes.h"
  35.  
  36. #ifdef HAVE_UTIL_H
  37. #include <util.h>
  38. #endif /* HAVE_UTIL_H */
  39.  
  40. #ifdef HAVE_SYS_IOCTL_H
  41. #include <sys/ioctl.h>
  42. #endif /* HAVE_SYS_IOCTL_H */
  43.  
  44. /* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */
  45. #if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY)
  46. #undef HAVE_DEV_PTMX
  47. #endif /* HAVE__GETPTY || HAVE_OPENPTY */
  48.  
  49. #ifdef HAVE_PTY_H
  50. #include <pty.h>
  51. #endif /* HAVE_PTY_H */
  52.  
  53. #ifndef O_NOCTTY
  54. #define O_NOCTTY 0
  55. #endif /* O_NOCTTY */
  56.  
  57. /*
  58.  * Allocates and opens a pty.  Returns -1 if no pty could be allocated, or
  59.  * zero if a pty was successfully allocated.  On success, open file
  60.  * descriptors for the pty and tty sides and the name of the tty side are
  61.  * returned (the buffer must be able to hold at least 64 characters).
  62.  */
  63.  
  64. int pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) {
  65. #if defined(HAVE_OPENPTY) || defined(BSD4_4)
  66.     /* openpty(3) exists in OSF/1 and some other os'es */
  67.     char buf[64];
  68.     int i;
  69.  
  70.     i = openpty(ptyfd, ttyfd, buf, NULL, NULL);
  71.     if (i < 0) {
  72.         ioerror("openpty");
  73.         return -1;
  74.     }
  75.     safecopy(namebuf, buf); /* possible truncation */
  76.     return 0;
  77. #else /* HAVE_OPENPTY */
  78. #ifdef HAVE__GETPTY
  79.     /*
  80.      * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
  81.      * pty's automagically when needed
  82.      */
  83.     char *slave;
  84.  
  85.     slave = _getpty(ptyfd, O_RDWR, 0622, 0);
  86.     if (slave == NULL) {
  87.         ioerror("_getpty");
  88.         return -1;
  89.     }
  90.     safecopy(namebuf, slave);
  91.     /* Open the slave side. */
  92.     *ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
  93.     if (*ttyfd < 0) {
  94.         ioerror(namebuf);
  95.         close(*ptyfd);
  96.         return -1;
  97.     }
  98.     return 0;
  99. #else /* HAVE__GETPTY */
  100. #if defined(HAVE_DEV_PTMX)
  101.     /*
  102.      * This code is used e.g. on Solaris 2.x.  (Note that Solaris 2.3
  103.      * also has bsd-style ptys, but they simply do not work.)
  104.      */
  105.     int ptm;
  106.     char *pts;
  107.  
  108.     ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY);
  109.     if (ptm < 0) {
  110.         ioerror("/dev/ptmx");
  111.         return -1;
  112.     }
  113.     if (grantpt(ptm) < 0) {
  114.         ioerror("grantpt");
  115.         /* return -1; */
  116.         /* Can you tell me why it doesn't work? */
  117.     }
  118.     if (unlockpt(ptm) < 0) {
  119.         ioerror("unlockpt");
  120.         return -1;
  121.     }
  122.     pts = ptsname(ptm);
  123.     if (pts == NULL)
  124.         log(LOG_ERR, "Slave pty side name could not be obtained");
  125.     safecopy(namebuf, pts);
  126.     *ptyfd = ptm;
  127.  
  128.     /* Open the slave side. */
  129.     *ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
  130.     if (*ttyfd < 0) {
  131.         ioerror(namebuf);
  132.         close(*ptyfd);
  133.         return -1;
  134.     }
  135.     /* Push the appropriate streams modules, as described in Solaris pts(7). */
  136.     if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
  137.         ioerror("ioctl I_PUSH ptem");
  138.     if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
  139.         ioerror("ioctl I_PUSH ldterm");
  140.     if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
  141.         ioerror("ioctl I_PUSH ttcompat");
  142.     return 0;
  143. #else /* HAVE_DEV_PTMX */
  144. #ifdef HAVE_DEV_PTS_AND_PTC
  145.     /* AIX-style pty code. */
  146.     const char *name;
  147.  
  148.     *ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY);
  149.     if (*ptyfd < 0) {
  150.         ioerror("open(/dev/ptc)");
  151.         return -1;
  152.     }
  153.     name = ttyname(*ptyfd);
  154.     if (!name) {
  155.         log(LOG_ERR, "Open of /dev/ptc returns device for which ttyname fails");
  156.         return -1;
  157.     }
  158.     safecopy(namebuf, name);
  159.     *ttyfd = open(name, O_RDWR | O_NOCTTY);
  160.     if (*ttyfd < 0) {
  161.         ioerror(name);
  162.         close(*ptyfd);
  163.         return -1;
  164.     }
  165.     return 0;
  166. #else /* HAVE_DEV_PTS_AND_PTC */
  167.     /* BSD-style pty code. */
  168.     char buf[64];
  169.     int i;
  170.     const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
  171.     const char *ptyminors = "0123456789abcdef";
  172.     int num_minors = strlen(ptyminors);
  173.     int num_ptys = strlen(ptymajors) * num_minors;
  174.  
  175.     for (i = 0; i < num_ptys; i++) {
  176. #ifdef HAVE_SNPRINTF
  177.         snprintf(buf, sizeof buf,
  178. #else
  179.         sprintf(buf,
  180. #endif
  181.              "/dev/pty%c%c", ptymajors[i / num_minors],
  182.              ptyminors[i % num_minors]);
  183.         *ptyfd = open(buf, O_RDWR | O_NOCTTY);
  184.         if (*ptyfd < 0)
  185.             continue;
  186. #ifdef HAVE_SNPRINTF
  187.         snprintf(namebuf, namebuflen,
  188. #else
  189.         sprintf(namebuf,
  190. #endif
  191.             "/dev/tty%c%c",
  192.             ptymajors[i / num_minors], ptyminors[i % num_minors]);
  193.  
  194.         /* Open the slave side. */
  195.         *ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
  196.         if (*ttyfd < 0) {
  197.             ioerror(namebuf);
  198.             close(*ptyfd);
  199.             return -1;
  200.         }
  201.         return 0;
  202.     }
  203.     return -1;
  204. #endif /* HAVE_DEV_PTS_AND_PTC */
  205. #endif /* HAVE_DEV_PTMX */
  206. #endif /* HAVE__GETPTY */
  207. #endif /* HAVE_OPENPTY */
  208. }
  209.  
  210. /* The code below is currently not used */
  211. #if 0
  212.  
  213. /* Releases the tty.  Its ownership is returned to root, and permissions to 0666. */
  214.  
  215. void pty_release(char *tty_name) {
  216.     if(chown(tty_name, (uid_t)0, (gid_t)0)<0)
  217.         log(LOG_DEBUG, "chown %.100s 0 0 failed: %.100s", tty_name,
  218.             strerror(get_last_socket_error()));
  219.     if(chmod(tty_name, (mode_t)0666)<0)
  220.         log(LOG_DEBUG, "chmod %.100s 0666 failed: %.100s", tty_name,
  221.             strerror(get_last_socket_error()));
  222. }
  223.  
  224. /* Makes the tty the processes controlling tty and sets it to sane modes. */
  225.  
  226. void pty_make_controlling_tty(int *ttyfd, char *tty_name) {
  227.     int fd;
  228.  
  229.     /* First disconnect from the old controlling tty. */
  230. #ifdef TIOCNOTTY
  231.     fd = open("/dev/tty", O_RDWR | O_NOCTTY);
  232.     if (fd >= 0) {
  233.         (void) ioctl(fd, TIOCNOTTY, NULL);
  234.         close(fd);
  235.     }
  236. #endif /* TIOCNOTTY */
  237.     if (setsid() < 0)
  238.         ioerror("setsid");
  239.  
  240.     /*
  241.      * Verify that we are successfully disconnected from the controlling
  242.      * tty.
  243.      */
  244.     fd = open("/dev/tty", O_RDWR | O_NOCTTY);
  245.     if (fd >= 0) {
  246.         log(LOG_ERR, "Failed to disconnect from controlling tty");
  247.         close(fd);
  248.     }
  249.     /* Make it our controlling tty. */
  250. #ifdef TIOCSCTTY
  251.     log(LOG_DEBUG, "Setting controlling tty using TIOCSCTTY");
  252.     /*
  253.      * We ignore errors from this, because HPSUX defines TIOCSCTTY, but
  254.      * returns EINVAL with these arguments, and there is absolutely no
  255.      * documentation.
  256.      */
  257.     ioctl(*ttyfd, TIOCSCTTY, NULL);
  258. #endif /* TIOCSCTTY */
  259.     fd = open(tty_name, O_RDWR);
  260.     if (fd < 0)
  261.         ioerror(tty_name);
  262.     else
  263.         close(fd);
  264.  
  265.     /* Verify that we now have a controlling tty. */
  266.     fd = open("/dev/tty", O_WRONLY);
  267.     if (fd < 0)
  268.         ioerror("open /dev/tty failed - could not set controlling tty");
  269.     else {
  270.         close(fd);
  271.     }
  272. }
  273.  
  274. #endif
  275.  
  276. /* End of pty.c */
  277.